/*
 *
 *  *
 *  *      Copyright 2020-2021 Luter.me
 *  *
 *  *      Licensed under the Apache License, Version 2.0 (the "License");
 *  *      you may not use this file except in compliance with the License.
 *  *      You may obtain a copy of the License at
 *  *
 *  *        http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *      Unless required by applicable law or agreed to in writing, software
 *  *      distributed under the License is distributed on an "AS IS" BASIS,
 *  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *      See the License for the specific language governing permissions and
 *  *      limitations under the License.
 *  *
 *
 */

package com.luter.heimdall.plugins.jwt.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.Objects;

/**
 * Jackson 工具类
 *
 * @author luter
 */
public final class JacksonUtil {
    /**
     * The constant OBJECT_MAPPER.
     */
    private static volatile ObjectMapper OBJECT_MAPPER;

    /**
     * Instantiates a new Jackson util.
     */
    private JacksonUtil() {
    }

    /**
     * Init object mapper.
     */
    private static void initObjectMapper() {
        ObjectMapper instance = new ObjectMapper();
        //FAIL_ON_UNKNOWN_PROPERTIES 主要是针对这个不存在的字段:UserDetails#getPrincipal()，遇到不存在字段的时候不要报错
        instance.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        ////////注册 泛型抽象类 jackson 处理器
//        SimpleModule module = new SimpleModule("GrantedAuthorityModel", Version.unknownVersion());
//        SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
//        resolver.addMapping(GrantedAuthority.class, SimpleGrantedAuthority.class);
//        resolver.addMapping(GrantedAuthority.class, MethodAndUrlGrantedAuthority.class);
//        module.setAbstractTypes(resolver);
//        instance.registerModule(module);
        OBJECT_MAPPER = instance;

    }

    /**
     * Gets object mapper.
     *
     * @return the object mapper
     */
    public static ObjectMapper getObjectMapper() {
        if (null == OBJECT_MAPPER) {
            initObjectMapper();
        }
        return OBJECT_MAPPER;
    }

    /**
     * Is char sequence boolean.
     *
     * @param object the object
     * @return the boolean
     */
    public static Boolean isCharSequence(Object object) {
        return !Objects.isNull(object) && isCharSequence(object.getClass());
    }

    /**
     * Is char sequence boolean.
     *
     * @param clazz the clazz
     * @return the boolean
     */
    public static boolean isCharSequence(Class<?> clazz) {
        return clazz != null && CharSequence.class.isAssignableFrom(clazz);
    }

    /**
     * To object t.
     *
     * @param <T>          the type parameter
     * @param jsonArrayStr the json array str
     * @param clazz        the clazz
     * @return the t
     */
    public static <T> T toObject(String jsonArrayStr, Class<T> clazz) {
        try {
            return getObjectMapper().readValue(jsonArrayStr, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * To json string.
     *
     * @param object the object
     * @return the string
     */
    public static String toJson(Object object) {
        if (isCharSequence(object)) {
            return (String) object;
        }
        try {
            return getObjectMapper().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * To pretty json string.
     *
     * @param object the object
     * @return the string
     */
    public static String toPrettyJson(Object object) {
        if (isCharSequence(object)) {
            return (String) object;
        }
        try {
            return getObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}
